﻿#include "../include/cat-hook.hpp"
#include "../include/util/base.hpp"
#include "../include/Header/cat-config.hpp"

#include<thread>
#include<mutex>
#include<map>
//#include <SFML\System\Sleep.hpp>

#include<SDL.h>

class Hook {
public:
	static Hook* GetInstance();

	static void ReleaseInstance();

	void Strat(int id);

	void Stop();

	void StartTick();

	void StopTick();

	void SwitchTarget(int id);

	bool GetExist()const { return isExist; };
	void SetExist(bool _isExist) { isExist = _isExist; };
	/****************************************************************************/
	/// <summary>
	/// 注册时钟事件 每秒触发一次(可更改)
	/// </summary>
	/// <param name="tick">需要绑定的时钟函数</param>
	/// <param name="id">时钟函数的id</param>
	/// <returns></returns>
	bool RegistTick(void* (*tick)(float), int id);
	/// <summary>
	/// 发送时钟事件
	/// </summary>
	/// <param name="_tick"></param>
	void SendTick(float _tick);
	/// <summary>
	/// 销毁时钟事件
	/// </summary>
	/// <param name="id">销毁时钟</param>
	void FireTick(int id);
	/****************************************************************************/
	/// <summary>
	/// 注册键盘事件
	/// </summary>
	/// <param name="key_press"></param>
	/// <param name="id"></param>
	/// <returns></returns>
	bool RegistKeyPress(void* (*key_press)(const cat_key_event* event, bool), int id);
	/// <summary>
	/// 发送键盘事件
	/// </summary>
	/// <param name="event"></param>
	/// <param name="_keyup"></param>
	void SendKeyPress(const cat_key_event* event, bool _keyup);
	/// <summary>
	/// 销毁键盘事件
	/// </summary>
	/// <param name="id"></param>
	void FireKeyPress(int id);
	/****************************************************************************/
	/// <summary>
	/// 注册鼠标点击事件
	/// </summary>
	/// <param name="_mouse_click"></param>
	/// <param name="id"></param>
	/// <returns></returns>
	bool RegistMouseClick(void* (*_mouse_click)(const cat_mouse_click_event* event, bool), int id);
	/// <summary>
	/// 发送鼠标点击事件
	/// </summary>
	/// <param name="event"></param>
	/// <param name=""></param>
	void SendMouseClick(const cat_mouse_click_event* event, bool);
	/// <summary>
	/// 销毁鼠标点击事件
	/// </summary>
	/// <param name="id"></param>
	void FireMouseClick(int id);
	/****************************************************************************/
	/// <summary>
	/// 注册鼠标移动事件
	/// </summary>
	/// <param name="_mouse_move"></param>
	/// <param name="id"></param>
	/// <returns></returns>
	bool RegistMouseMove(void* (*_mouse_move)(const cat_mouse_move_event* event),int id);
	/// <summary>
	/// 发送鼠标移动事件
	/// </summary>
	/// <param name="event"></param>
	void SendMouseMove(const cat_mouse_move_event* event);
	/// <summary>
	/// 销毁鼠标移动事件
	/// </summary>
	/// <param name="id"></param>
	void FireMouseMove(int id);
	/****************************************************************************/
	bool RegistForceMouseMove(void* (*_force_mouse_move)(const cat_mouse_move_event* event),int id);

	void SendForceMouseMove(const cat_mouse_move_event* event);

	void FireForceMouseMove(int id);
	/****************************************************************************/
	bool RegistJoyButtonPress(void* (*joystick_button_press)(const cat_joystick_button_event* event, bool), int id);

	void SendJoyButtonPress(const cat_joystick_button_event* event, bool);

	void FireJoyButtonPress(int id);
	/****************************************************************************/
	bool RegistJoyAxiseMove(void* (*joystick_axis_move)(const cat_joystick_axis_move_event* event), int id);

	void SendJoyAxiseMove(const cat_joystick_axis_move_event* event);

	void FireJoyAxiseMove(int id);
	/****************************************************************************/
private:
	Hook();

	~Hook();

	void Run(int id);

	void TickTock();
	
	bool isExist,isTickExist;

	std::thread* th;
	std::thread* tickth;

	int joyId;
	
	std::mutex mtick, mkeypress, mmouseclick,mmousemove, mfmousemove,mjoybutton,mjoyaxis;

	std::map<int, void* (*)(float)> tick;
	std::map<int, void* (*)(const cat_key_event* event, bool)> key_press;
	std::map<int, void* (*)(const cat_mouse_click_event* event, bool)> mouse_click;
	std::map<int, void* (*)(const cat_mouse_move_event* event)> mouse_move;
	std::map<int, void* (*)(const cat_mouse_move_event* event)> mouse_force_move;
	std::map<int, void* (*)(const cat_joystick_button_event* event, bool)> cat_joystick_button;
	std::map<int, void* (*)(const cat_joystick_axis_move_event* event)> cat_joystick_axis_move;
};

namespace {
	
	Hook *s_instance = NULL;

	SDL_bool retval = SDL_FALSE;
	SDL_bool DisCont = SDL_FALSE;
}

Hook *Hook::GetInstance()
{
	if (s_instance == NULL) {
		s_instance = new Hook();
	}
	return s_instance;
}

void Hook::ReleaseInstance()
{
	if (s_instance != NULL) {
		delete s_instance;
	}

	s_instance = NULL;
}

Hook::Hook() :
	isExist(false),
	isTickExist(false),
	th(NULL),
	tickth(NULL),
	joyId(0)
{
}

Hook::~Hook() {
	tick.clear();
	key_press.clear();
	mouse_click.clear();
	mouse_move.clear();
	mouse_force_move.clear();
	cat_joystick_button.clear();
	cat_joystick_axis_move.clear();
}

void Hook::Strat(int id)
{
	isExist = false;
	th = new std::thread(&Hook::Run, this,id);
}

void Hook::Stop() {
	isExist = true;
	th->join();
	delete th;
	th = NULL;
}

void Hook::SwitchTarget(int id) {
	if (joyId != id) {
		Stop();
		Strat(id);	
	}
}

void Hook::StartTick() {
	isTickExist = false;
	tickth = new std::thread(&Hook::TickTock, this);
}

void Hook::StopTick() {

	isTickExist = true;
	tickth->join();
	delete tickth;
	tickth = NULL;	
}

void Hook::TickTock() {
	while(!isTickExist){
		SendTick(static_cast<float>(CAT_TICK_TIME) / 1000.0f);
		SDL_Delay(CAT_TICK_TIME);
	}
}

void
loop(void* arg)
{
	SDL_Event event;
	int i;
	SDL_Joystick* joystick = (SDL_Joystick*)arg;

	/* blank screen, set up for drawing this frame. 
	SDL_SetRenderDrawColor(screen, 0x0, 0x0, 0x0, SDL_ALPHA_OPAQUE);
	SDL_RenderClear(screen);*/

	while (!Hook::GetInstance()->GetExist() && SDL_WaitEventTimeout(&event, 500) == 1) {
		switch (event.type) {
		case SDL_JOYDEVICEREMOVED:
			SDL_Log("Joystick device %d removed.\n", (int)event.jdevice.which);
			SDL_Log("Our instance ID is %d\n", (int)SDL_JoystickInstanceID(joystick));
			DisCont = SDL_TRUE;
			break;
		case SDL_JOYAXISMOTION: {
			/*
			SDL_Log("Joystick %d axis %d value: %d\n",
				event.jaxis.which,
				event.jaxis.axis, event.jaxis.value);*/
			const cat_joystick_axis_move_event joy_event = { event.jaxis.axis ,event.jaxis.value };
			Hook::GetInstance()->SendJoyAxiseMove(&joy_event);
			}
			break;
		case SDL_JOYHATMOTION:
			SDL_Log("Joystick %d hat %d value:",
				event.jhat.which, event.jhat.hat);
			if (event.jhat.value == SDL_HAT_CENTERED)
				SDL_Log(" centered");
			if (event.jhat.value & SDL_HAT_UP)
				SDL_Log(" up");
			if (event.jhat.value & SDL_HAT_RIGHT)
				SDL_Log(" right");
			if (event.jhat.value & SDL_HAT_DOWN)
				SDL_Log(" down");
			if (event.jhat.value & SDL_HAT_LEFT)
				SDL_Log(" left");
			SDL_Log("\n");
			break;
		case SDL_JOYBALLMOTION:
			SDL_Log("Joystick %d ball %d delta: (%d,%d)\n",
				event.jball.which,
				event.jball.ball, event.jball.xrel, event.jball.yrel);
			break;
		case SDL_JOYBUTTONDOWN: {
			/*
			SDL_Log("Joystick %d button %d down\n",
				event.jbutton.which, event.jbutton.button);*/
			const cat_joystick_button_event joy_button_down_event = { event.jbutton.button };
			Hook::GetInstance()->SendJoyButtonPress(&joy_button_down_event,false);
			}
			break;
		case SDL_JOYBUTTONUP: {/*
			SDL_Log("Joystick %d button %d up\n",
				event.jbutton.which, event.jbutton.button);*/
			const cat_joystick_button_event joy_button_up_event = { event.jbutton.button };
			Hook::GetInstance()->SendJoyButtonPress(&joy_button_up_event, true);
			}
			break;		
		default:
			break;
		}
	}
	
	if (SDL_JoystickGetAttached(joystick) == 0) {
		retval = SDL_TRUE;  /* keep going, wait for reattach. */
	}

#ifdef __EMSCRIPTEN__
	if (done) {
		emscripten_cancel_main_loop();
	}
#endif
}

static SDL_bool
WatchJoystick(SDL_Joystick* joystick)
{
	const char* name = NULL;

	/* Print info about the joystick we are watching */
	name = SDL_JoystickName(joystick);
	SDL_Log("Watching joystick %d: (%s)\n", SDL_JoystickInstanceID(joystick),
		name ? name : "Unknown Joystick");
	SDL_Log("Joystick has %d axes, %d hats, %d balls, and %d buttons\n",
		SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
		SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
	
	DisCont = SDL_FALSE;
	/* Loop, getting joystick events! */
#ifdef __EMSCRIPTEN__
	emscripten_set_main_loop_arg(loop, joystick, 0, 1);
#else
	while (!Hook::GetInstance()->GetExist()&& !DisCont) {
		loop(joystick);
	}
#endif
	return retval;
}

void Hook::Run(int id) {

	joyId = id;

	const char* name, * type;
	int i,m_device_id;
	SDL_Joystick* joystick;

	SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");

	/* Enable standard application logging */
	SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);

	/* Initialize SDL (Note: video is required to start event loop) */
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
		SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
		return;
	}

	/* Print information about the joysticks */
	SDL_Log("There are %d joysticks attached\n", SDL_NumJoysticks());
	for (i = 0; i < SDL_NumJoysticks(); ++i) {
		name = SDL_JoystickNameForIndex(i);
		SDL_Log("Joystick %d: %s\n", i, name ? name : "Unknown Joystick");
		joystick = SDL_JoystickOpen(i);
		if (joystick == NULL) {
			SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_JoystickOpen(%d) failed: %s\n", i,
				SDL_GetError());
		}
		else {
			char guid[64];
			SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
			SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick),
				guid, sizeof(guid));
			switch (SDL_JoystickGetType(joystick)) {
			case SDL_JOYSTICK_TYPE_GAMECONTROLLER:
				type = "Game Controller";
				break;
			case SDL_JOYSTICK_TYPE_WHEEL:
				type = "Wheel";
				break;
			case SDL_JOYSTICK_TYPE_ARCADE_STICK:
				type = "Arcade Stick";
				break;
			case SDL_JOYSTICK_TYPE_FLIGHT_STICK:
				type = "Flight Stick";
				break;
			case SDL_JOYSTICK_TYPE_DANCE_PAD:
				type = "Dance Pad";
				break;
			case SDL_JOYSTICK_TYPE_GUITAR:
				type = "Guitar";
				break;
			case SDL_JOYSTICK_TYPE_DRUM_KIT:
				type = "Drum Kit";
				break;
			case SDL_JOYSTICK_TYPE_ARCADE_PAD:
				type = "Arcade Pad";
				break;
			case SDL_JOYSTICK_TYPE_THROTTLE:
				type = "Throttle";
				break;
			default:
				type = "Unknown";
				break;
			}
			SDL_Log("       type: %s\n", type);
			SDL_Log("       axes: %d\n", SDL_JoystickNumAxes(joystick));
			SDL_Log("      balls: %d\n", SDL_JoystickNumBalls(joystick));
			SDL_Log("       hats: %d\n", SDL_JoystickNumHats(joystick));
			SDL_Log("    buttons: %d\n", SDL_JoystickNumButtons(joystick));
			SDL_Log("instance id: %d\n", SDL_JoystickInstanceID(joystick));
			SDL_Log("       guid: %s\n", guid);
			SDL_Log("    VID/PID: 0x%.4x/0x%.4x\n", SDL_JoystickGetVendor(joystick), SDL_JoystickGetProduct(joystick));
			SDL_JoystickClose(joystick);
		}
	}
	if (joyId <= SDL_NumJoysticks()) {
		m_device_id = joyId;
	}
	else
		m_device_id = 0;

#if defined(__ANDROID__) || defined(__IPHONEOS__)
	if (SDL_NumJoysticks() > 0) {
#else
	if ( id>=0 && id<=8 ) {
#endif
		SDL_bool reportederror = SDL_FALSE;
		SDL_bool keepGoing = SDL_TRUE;
		SDL_Event event;
		int device;
#if defined(__ANDROID__) || defined(__IPHONEOS__)
		device = 0;
#else
		device = m_device_id;
#endif
		joystick = SDL_JoystickOpen(device);
		if (joystick != NULL) {
			SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
		}

		while (!isExist) {
			if (joystick == NULL) {
				if (!reportederror) {
					SDL_Log("Couldn't open joystick %d: %s\n", device, SDL_GetError());
					reportederror = SDL_TRUE;
				}
			}
			else {
				reportederror = SDL_FALSE;
				keepGoing = WatchJoystick(joystick);
				SDL_JoystickClose(joystick);
			}

			joystick = NULL;
			while (!isExist && SDL_WaitEventTimeout(&event,500)==1) {
				if (event.type == SDL_JOYDEVICEADDED) {
					device = event.jdevice.which;
					joystick = SDL_JoystickOpen(device);
					if (joystick != NULL) {
						SDL_assert(SDL_JoystickFromInstanceID(SDL_JoystickInstanceID(joystick)) == joystick);
					}
					break;
				}
			}
		}
	}

	SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK);

	return;
}

bool Hook::RegistTick(void* (*_tick)(float), int id)
{
	if (!_tick)
		return false;

	if (mtick.try_lock()) {
		std::pair<std::map<int, void* (*)(float)>::iterator, bool> Insert_Pair;
		Insert_Pair = tick.insert(std::pair<int, void* (*)(float)>(id, _tick));
		mtick.unlock();
		return Insert_Pair.second;
	}
	return false;
}

void Hook::SendTick(float _tick)
{
	if (mtick.try_lock()) {
		for (auto entry = tick.begin(); entry != tick.end(); entry++)
		{
			entry->second(_tick);
		}
		mtick.unlock();
	}
}

void Hook::FireTick(int id)
{
	if (mtick.try_lock()) {
		tick.erase(id);
		mtick.unlock();
	}
}

bool Hook::RegistKeyPress(void* (*_key_press)(const cat_key_event* event, bool), int id)
{
	if (!_key_press)
		return false;

	if (mkeypress.try_lock()) {
		std::pair<std::map<int, void* (*)(const cat_key_event* event, bool)>::iterator, bool> Insert_Pair;
		Insert_Pair = key_press.insert(std::pair<int, void* (*)(const cat_key_event* event, bool)>(id, _key_press));
		mkeypress.unlock();
		return Insert_Pair.second;
	}

	return false;
}

void Hook::SendKeyPress(const cat_key_event* event, bool _keyup)
{
	if (mkeypress.try_lock()) {
		for (auto entry = key_press.begin(); entry != key_press.end(); entry++)
		{
			entry->second(event, _keyup);
		}
		mkeypress.unlock();
	}
}

void Hook::FireKeyPress(int id)
{
	if (mkeypress.try_lock()) {
		key_press.erase(id);
		mkeypress.unlock();
	}
}

bool Hook::RegistMouseClick(void* (*_mouse_click)(const cat_mouse_click_event* event, bool), int id)
{
	if (!_mouse_click)
		return false;

	if (mmouseclick.try_lock()) {
		std::pair<std::map<int, void* (*)(const cat_mouse_click_event* event, bool)>::iterator, bool> Insert_Pair;
		Insert_Pair = mouse_click.insert(std::pair<int, void* (*)(const cat_mouse_click_event* event, bool)>(id, _mouse_click));
		mmouseclick.unlock();

		return Insert_Pair.second;
	}
	return false;
}

void Hook::SendMouseClick(const cat_mouse_click_event* event, bool _keyup)
{
	if (mmouseclick.try_lock()) {
		for (auto entry = mouse_click.begin(); entry != mouse_click.end(); entry++)
		{
			entry->second(event, _keyup);
		}
		mmouseclick.unlock();
	}
}

void Hook::FireMouseClick(int id)
{
	if (mmouseclick.try_lock()) {
		mouse_click.erase(id);
		mmouseclick.unlock();
	}
}

bool Hook::RegistMouseMove(void* (*_mouse_move)(const cat_mouse_move_event* event), int id)
{
	if (!_mouse_move)
		return false;

	if (mmousemove.try_lock()) {
		std::pair<std::map<int, void* (*)(const cat_mouse_move_event* event)>::iterator, bool> Insert_Pair;
		Insert_Pair = mouse_move.insert(std::pair<int, void* (*)(const cat_mouse_move_event* event)>(id, _mouse_move));
		mmousemove.unlock();

		return Insert_Pair.second;
	}
	return false;
}

void Hook::SendMouseMove(const cat_mouse_move_event* event)
{
	if (mmousemove.try_lock()) {
		for (auto entry = mouse_move.begin(); entry != mouse_move.end(); entry++) {
			entry->second(event);
		}
		mmousemove.unlock();
	}
}

void Hook::FireMouseMove(int id)
{
	if (mmousemove.try_lock()) {
		mouse_move.erase(id);
		mmousemove.unlock();
	}
}

bool Hook::RegistForceMouseMove(void* (*_force_mouse_move)(const cat_mouse_move_event* event), int id)
{
	if (!_force_mouse_move)
		return false;

	if (mfmousemove.try_lock()) {
		std::pair<std::map<int, void* (*)(const cat_mouse_move_event* event)>::iterator, bool> Insert_Pair;
		Insert_Pair = mouse_force_move.insert(std::pair<int, void* (*)(const cat_mouse_move_event* event)>(id, _force_mouse_move));
		mfmousemove.unlock();

		return Insert_Pair.second;
	}
	return false;
}

void Hook::SendForceMouseMove(const cat_mouse_move_event* event)
{
	if (mfmousemove.try_lock()) {
		for (auto entry = mouse_force_move.begin(); entry != mouse_force_move.end(); entry++) {
			entry->second(event);
		}
		mfmousemove.unlock();
	}
}

void Hook::FireForceMouseMove(int id)
{
	if (mfmousemove.try_lock()) {
		mouse_force_move.erase(id);
		mfmousemove.unlock();
	}
}

bool Hook::RegistJoyButtonPress(void* (*joystick_button_press)(const cat_joystick_button_event* event, bool), int id)
{
	if (!joystick_button_press)
		return false;

	if (mjoybutton.try_lock()) {
		std::pair<std::map<int, void* (*)(const cat_joystick_button_event* event, bool)>::iterator, bool> Insert_Pair;
		Insert_Pair = cat_joystick_button.insert(std::pair<int, void* (*)(const cat_joystick_button_event* event, bool)>(id, joystick_button_press));
		mjoybutton.unlock();

		return Insert_Pair.second;
	}

	return false;
}

void Hook::SendJoyButtonPress(const cat_joystick_button_event* event, bool up)
{
	if (mjoybutton.try_lock()) {
		for (auto entry = cat_joystick_button.begin(); entry != cat_joystick_button.end(); entry++) {
			entry->second(event,up);
		}
		mjoybutton.unlock();
	}
}

void Hook::FireJoyButtonPress(int id)
{
	if (mjoybutton.try_lock()) {
		cat_joystick_button.erase(id);
		mjoybutton.unlock();
	}
}

bool Hook::RegistJoyAxiseMove(void* (*joystick_axis_move)(const cat_joystick_axis_move_event* event), int id)
{
	if (!joystick_axis_move)
		return false;

	if (mjoyaxis.try_lock()) {
		std::pair<std::map<int, void* (*)(const cat_joystick_axis_move_event* event)>::iterator, bool> Insert_Pair;
		Insert_Pair = cat_joystick_axis_move.insert(std::pair<int, void* (*)(const cat_joystick_axis_move_event* event)>(id, joystick_axis_move));
		mjoyaxis.unlock();

		return Insert_Pair.second;
	}

	return false;
}

void Hook::SendJoyAxiseMove(const cat_joystick_axis_move_event* event)
{
	if (mjoyaxis.try_lock()) {
		for (auto entry = cat_joystick_axis_move.begin(); entry != cat_joystick_axis_move.end(); entry++) {
			entry->second(event);
		}
		mjoyaxis.unlock();
	}
}

void Hook::FireJoyAxiseMove(int id)
{
	if (mjoyaxis.try_lock()) {
		cat_joystick_axis_move.erase(id);
		mjoyaxis.unlock();
	}
}

/**********************************************************************************************/

void cat_hook_start(int id)
{
	Hook::GetInstance()->Strat(id);
}

void cat_hook_stop()
{
	Hook::GetInstance()->Stop();
}

void cat_hook_switch_target(int id)
{
	Hook::GetInstance()->SwitchTarget(id);
}

void cat_ticktock_start()
{
	Hook::GetInstance()->StartTick();
}

void cat_ticktock_stop()
{
	Hook::GetInstance()->StopTick();
}

bool cat_hook_regist_tick(void* (*tick)(float), int id)
{

	return Hook::GetInstance()->RegistTick(tick,id);
}

void cat_hook_fire_tick(int id)
{
	return Hook::GetInstance()->FireTick(id);
}

bool cat_hook_regist_key_press(void* (*key_press)(const cat_key_event* event, bool), int id)
{
	return Hook::GetInstance()->RegistKeyPress(key_press,id);
}

void cat_hook_fire_key_press(int id)
{
	Hook::GetInstance()->FireKeyPress(id);
}

bool cat_hook_regist_mouse_click(void* (*mouse_click)(const cat_mouse_click_event* event, bool), int id)
{
	return Hook::GetInstance()->RegistMouseClick(mouse_click,id);
}

void cat_hook_fire_mouse_click(int id)
{
	return  Hook::GetInstance()->FireMouseClick(id);
}

bool cat_hook_regist_mouse_move(void* (*mouse_move)(const cat_mouse_move_event* event), int id)
{
	return Hook::GetInstance()->RegistMouseMove(mouse_move,id);
}

void cat_hook_fire_mouse_move(int id)
{
	return Hook::GetInstance()->FireMouseMove(id);
}

bool cat_hook_regist_force_mouse_move(void* (*force_mouse_move)(const cat_mouse_move_event* event), int id)
{
	return Hook::GetInstance()->RegistForceMouseMove(force_mouse_move,id);
}

void cat_hook_fire_force_mouse_move(int id)
{
	Hook::GetInstance()->FireForceMouseMove(id);
}

bool cat_hook_regist_joystick_button_press(void* (*joystick_button_press)(const cat_joystick_button_event* event, bool), int id)
{
	return Hook::GetInstance()->RegistJoyButtonPress(joystick_button_press,id);
}

void cat_hook_fire_joystick_button_press(int id)
{
	Hook::GetInstance()->FireJoyButtonPress(id);
}

bool cat_hook_regist_joystick_axis_move(void* (*joystick_axis_move)(const cat_joystick_axis_move_event* event), int id)
{
	return Hook::GetInstance()->RegistJoyAxiseMove(joystick_axis_move,id);
}

void cat_hook_fire_joystick_axis_move(int id)
{
	Hook::GetInstance()->FireJoyAxiseMove(id);
}

void  cat_send_key_press(const cat_key_event* event, bool _keyup)
{
	Hook::GetInstance()->SendKeyPress(event, _keyup);
}

void cat_send_mouse_click(const cat_mouse_click_event* event, bool _keyup)
{
	Hook::GetInstance()->SendMouseClick(event, _keyup);
}

void cat_send_mouse_move(const cat_mouse_move_event* event)
{
	Hook::GetInstance()->SendMouseMove(event);
}

void cat_send_force_mouse_move(const cat_mouse_move_event* event)
{
	Hook::GetInstance()->SendForceMouseMove(event);
}